package com.simon.train.member.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.simon.train.common.exception.BusinessException;
import com.simon.train.common.exception.BusinessExceptionEnum;
import com.simon.train.common.util.JwtUtil;
import com.simon.train.common.util.SnowUtil;
import com.simon.train.member.domain.Member;
import com.simon.train.member.domain.MemberExample;
import com.simon.train.member.dto.MemberDto;
import com.simon.train.member.dto.MemberLoginDto;
import com.simon.train.member.dto.MemberSendCodeDto;
import com.simon.train.member.mapper.MemberMapper;
import com.simon.train.member.vo.MemberLoginVO;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class MemberService {

    private static final Logger LOG = LoggerFactory.getLogger(MemberService.class);

    @Resource  //用Autowired注解需要加 @Mapper注解 用@Resource就可以不加
    private MemberMapper memberMapper;

    /**
     * 测试代码
     * @return
     */
    public int count(){
        return Math.toIntExact(memberMapper.countByExample(null));
    }

    /**
     * 会员用户注册
     * @param memberDto
     * @return
     */
    public long register(MemberDto memberDto){
        //先要进行一下校验 手机号不能重复
        String mobile = memberDto.getMobile();

        //2.也需要去查询手机号是否存在
        Member members = selectMemberByMobile(mobile);

        if(ObjectUtil.isNotNull(members)){
//            return memberList.get(0).getId();
            throw new BusinessException(BusinessExceptionEnum.MEMBER_MOBILE_EXIST);
            //throw new RuntimeException("该手机号已经被注册了");
        }
        Member member = Member
                .builder()
                .mobile(mobile)
                .id(SnowUtil.getSnowflakeNextId())
                .build();
        memberMapper.insert(member);
        return member.getId();
    }


    /**
     * 发送验证码的业务层
     * 通过点击获取验证码 对输入的手机发送验证码 如果手机号没有注册过 则直接把手机号写入数据库中默认创建账号
     * TODO:未来会继续完善验证码的模块 这里仅仅是测试 所以验证码模块写死
     * @param memberSendCodeDto
     */
    public void SendCode(MemberSendCodeDto memberSendCodeDto){
        //先要进行一下校验 手机号不能重复
        String mobile = memberSendCodeDto.getMobile();
        //2.也需要去查询手机号是否存在
        Member members = selectMemberByMobile(mobile);

        //如果手机号不存在 则插入手机号新记录
        if(ObjectUtil.isNull(members)){
            LOG.info("手机号不存在，插入一条记录");
            Member member = Member
                    .builder()
                    .mobile(mobile)
                    .id(SnowUtil.getSnowflakeNextId())
                    .build();
            memberMapper.insert(member);
        }else{
            LOG.info("手机号存在，无需注册！");
        }

        //生成验证码
        //String randomString = RandomUtil.randomString(4);

        /**
         * 为了便于我们调试 测试环境把验证码固定为四个8
         */
        String randomString = "8888";
        LOG.info("生成短信验证码:{}",randomString);

        // Todo:保存短信记录表 （这里暂时不开发）未来：手机号，短信验证码，有效期，是否已使用，业务类型，发送时间，使用时间
        LOG.info("保存短信记录表");

        //Todo: 对接短信通道，发送短信
        LOG.info("对接短信通道");


    }


    /**
     * 用户登录模块的业务层
     * @param memberLoginDto
     */
    public MemberLoginVO Login(MemberLoginDto memberLoginDto){

        //1.先获取两个参数
        String mobile = memberLoginDto.getMobile();
        String code = memberLoginDto.getCode();

        //2.也需要去查询手机号是否存在
        Member members = selectMemberByMobile(mobile);

        //手机号不存在 说明用户并没有去点击获取验证码 所以手机号压根没有被注册
        //需要抛出异常 让用户先去获取验证码
        if(ObjectUtil.isNull(members)){
            throw new BusinessException(BusinessExceptionEnum.MEMBER_MOBILE_NOT_EXIST);
        }

        //此时手机号已经存在 接下来我们需要去校验短信的验证码
        // TODO:为了便于测试写死 非高并发所以验证码可以写数据库 这里理论上要根据号码去数据库查验证码然后和用户的输入比较
        //这里为了便于测试直接写死为8888
        if( !"8888".equals(code) ){
            throw new BusinessException(BusinessExceptionEnum.MOBILE_CODE_ERROR);
        }

        //一般我们接下来要把查到的用户直接返回给前端 但是members里有密码等 我们要封装vo返回给前端
        MemberLoginVO memberLoginVO = new MemberLoginVO();
        BeanUtils.copyProperties(members,memberLoginVO);

        /**
         * 这段代码经过测试 没有问题 所以经过封装变成JWTUtil
         */
//        Map<String, Object> map = BeanUtil.beanToMap(memberLoginVO);
//        String key = "test123";
//        String token = JWTUtil.createToken(map, key.getBytes());

        String token = JwtUtil.createToken(memberLoginVO.getId(), memberLoginVO.getMobile());

        memberLoginVO.setToken(token);

        return memberLoginVO;

    }

    /**
     * 使用比较频繁 我们直接抽象成一个私有方法去使用
     * 根据手机号去查询是否存在对应的用户是否存在 返回有值或者空
     * @param mobile
     * @return
     */
    private Member selectMemberByMobile(String mobile) {
        MemberExample memberExample = new MemberExample();
        memberExample.createCriteria().andMobileEqualTo(mobile);
        List<Member> members = memberMapper.selectByExample(memberExample);

        if(CollUtil.isEmpty(members)){
            return null;
        }else{
            return members.get(0); //只有可能查出来一个 直接把查到的返回回去即可
        }
    }

}
